package com.ruoyi.dingtalk;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.json.JSONUtil;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.*;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response;
import com.dingtalk.api.response.OapiUserCountResponse;
import com.dingtalk.api.response.OapiV2UserGetuserinfoResponse;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.dingtalk.model.*;
import lombok.Data;
import lombok.Setter;
import lombok.SneakyThrows;
import org.apache.http.client.HttpResponseException;

import java.util.ArrayList;
import java.util.List;

/**
 * 钉钉api工具类
 *
 * @author yql
 */
@Data
public class ApiUtils {

    @Setter
    private static String accessToken;

    @Setter
    private static DingTalkModel model = new DingTalkModel();

    /**
     * 免登录
     *
     * @param code 前端code
     * @return 用户信息 {@link  LoginUserInfo}
     */
    @SneakyThrows
    public static LoginUserInfo getUserInfo(String code) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getuserinfo");
        OapiV2UserGetuserinfoRequest req = new OapiV2UserGetuserinfoRequest();
        req.setCode(code);
        OapiV2UserGetuserinfoResponse rsp = client.execute(req, accessToken);
        return JSONUtil.toBean(rsp.getBody(), BaseResponse.class).getResult(LoginUserInfo.class);
    }


    /**
     * 获取 token
     *
     * @return {@link Token}
     */

    @SneakyThrows
    public static Token gettoken() {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
        OapiGettokenRequest request = new OapiGettokenRequest();
        request.setAppkey(model.getAppKey());
        request.setAppsecret(model.getAppSecret());
        request.setHttpMethod("GET");
        OapiGettokenResponse response = client.execute(request);
        return JSONUtil.toBean(response.getBody(), Token.class);
    }

    /**
     * 用户数量
     *
     * @return {@link UserCount}
     */

    @SneakyThrows
    public static UserCount userCount() {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/count");
        OapiUserCountRequest req = new OapiUserCountRequest();
        req.setOnlyActive(false);
        OapiUserCountResponse rsp = client.execute(req, accessToken);
        BaseResponse bean = JSONUtil.toBean(rsp.getBody(), BaseResponse.class);
        return bean.getResult(UserCount.class);
    }

    /**
     * 获取部门列表
     *
     * @param deptId 部门ID
     * @return 部门列表{
     * "errcode": 0,
     * "errmsg":"ok",
     * "result": [{@link DeptInfo}],
     * "request_id": "5um7ykyaalsj"
     * }
     */
    @SneakyThrows
    public static BaseListResponse departmentListSub(Long deptId) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsub");
        OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest();
        req.setDeptId(deptId);
        req.setLanguage("zh_CN");
        return JSONUtil.toBean(client.execute(req, accessToken).getBody(), BaseListResponse.class);
    }

    /**
     * 获取部门列表
     *
     * @return 部门列表 {
     * "errcode": 0,
     * "errmsg":"ok",
     * "result": [{@link DeptInfo}],
     * "request_id": "5um7ykyaalsj"
     * }
     */
    @SneakyThrows
    public static BaseListResponse departmentListSub() {
        return departmentListSub(null);
    }

    /**
     * 获取所有部门
     *
     * @return 部门列表  [{@link DeptInfo}]
     */
    @SneakyThrows
    public static List<DeptInfo> departmentAll(String accessToken) {
        return departmentListRecursion(null);
    }

    /**
     * 获取所有部门树形结构
     *
     * @return 部门列表  [
     * {@link DeptInfo}
     * ]
     */
    @SneakyThrows
    public static List<DeptInfo> departmentTreeAll(String accessToken) {
        return departmentListRecursionTree(null);
    }

    public static List<DeptInfo> departmentListRecursion(Long deptId) {
        BaseListResponse baseListResponse = departmentListSub(deptId);
        List<DeptInfo> list = baseListResponse.getResult(DeptInfo.class);
        if (list != null && !list.isEmpty()) {
            for (int i = list.size() - 1; i >= 0; i--) {
                DeptInfo deptInfo = list.get(i);
                list.addAll(departmentListRecursion(deptInfo.getDept_id()));
            }
        }
        return list;
    }

    public static List<DeptInfo> departmentListRecursionTree(Long deptId) {
        BaseListResponse baseListResponse = departmentListSub(deptId);
        List<DeptInfo> list = baseListResponse.getResult(DeptInfo.class);
        if (list != null && !list.isEmpty()) {
            for (DeptInfo info : list) {
                info.setChildren(departmentListRecursionTree(info.getDept_id()));
            }
        }
        return list;
    }

    /**
     * 获取所有部门所有用户信息
     *
     * @return 用户列表 [{@link UserInfo}]
     */
    @SneakyThrows
    public static List<UserInfo> deptUserAll() {
        List<UserInfo> result = userListAll(1L);
        List<DeptInfo> deptList = departmentAll(accessToken);
        for (DeptInfo info : deptList) {
            result.addAll(userListAll(info.getDept_id()));
        }
        for (int i = 0; i < result.size(); i++) {
            for (int j = i + 1; j < result.size(); j++) {
                if (result.get(i).getUnionid().equals(result.get(j).getUnionid())) {
                    result.remove(j);
                    j--;
                }
            }
        }
        return result;
    }

    /**
     * @param deptId 部门id
     * @return 部门成员列表 {
     * "errcode": 0,
     * "errmsg":"ok",
     * "result": {
     * "userid_list": [{@link UserInfo} ]
     * },
     * "request_id": "3naksldjh0dk"
     * }
     */
    @SneakyThrows
    public static UserInfo userListId(Long deptId) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/listid");
        OapiUserListidRequest req = new OapiUserListidRequest();
        req.setDeptId(deptId);
        return JSONUtil.toBean(client.execute(req, accessToken).getBody(), BaseResponse.class).getResult(UserInfo.class);
    }

    /**
     * 获取当前部门用户信息列表
     *
     * @param deptId 部门id
     * @param cursor 开始游标
     * @param size   数量
     * @return 用户数据 [{@link UserInfo}]
     * },
     * "errmsg":"ok"
     * }
     */
    @SneakyThrows
    public static BasePageResponse userList(Long deptId, Long cursor, Long size) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/list");
        OapiV2UserListRequest req = new OapiV2UserListRequest();
        req.setDeptId(deptId);
        req.setCursor(cursor);
        req.setSize(size);
        req.setOrderField("modify_desc");
        req.setContainAccessLimit(false);
        req.setLanguage("zh_CN");
        return JSONUtil.toBean(client.execute(req, accessToken).getBody(), BasePageResponse.class);
    }

    /**
     * 获取当前部门所有用户信息列表
     *
     * @param deptId 部门id
     * @return 用户数据 [{@link UserInfo}]
     */

    @SneakyThrows
    public static List<UserInfo> userListAll(Long deptId) {
        List<UserInfo> result = new ArrayList<>();
        Long cursor = 0L;
        while (true) {
            BasePageResponse data = userList(deptId, cursor, 50L);
            if (data.getErrcode() != 0) {
                throw new HttpResponseException(Math.toIntExact(data.getErrcode()), data.getErrmsg());
            }
            BasePageResult baseResult = data.getResult();
            result.addAll(baseResult.getList(UserInfo.class));
            if (Boolean.FALSE.equals(baseResult.getHas_more())) {
                break;
            }
            cursor = baseResult.getNext_cursor();
        }
        return result;
    }

    /**
     * 发送信息
     *
     * @param userIdList 用户id列表
     * @param msgType    信息列表
     * @param message    信息本体
     * @return {@link AsyncSendResponse }
     */
    @SneakyThrows
    public static AsyncSendResponse asyncsendV2(List<String> userIdList, String msgType, String message) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2");
        OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
        request.setAgentId(model.getAgentId());
        request.setUseridList(StringUtils.join(userIdList, ","));
        request.setToAllUser(false);

        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype(msgType);
        if (msgType.equals("text")) {
            msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());
            msg.getText().setContent(message);
        } else if (msgType.equals("action_card")) {
            msg.setActionCard(JSONUtil.toBean(message, OapiMessageCorpconversationAsyncsendV2Request.ActionCard.class));
        }

        request.setMsg(msg);
        OapiMessageCorpconversationAsyncsendV2Response rsp = client.execute(request, accessToken);

        return JSONUtil.toBean(rsp.getBody(), AsyncSendResponse.class);
    }

    /**
     * 发送文本信息
     *
     * @param userIdList 用户id列表
     * @param message    信息本体
     * @return {@link AsyncSendResponse }
     */
    public static AsyncSendResponse asyncsendText2UserList(List<String> userIdList, String message) {
        return asyncsendV2(userIdList, "text", message);
    }

    /**
     * 发送文本信息
     *
     * @param userId  用户id
     * @param message 信息本体
     * @return {@link AsyncSendResponse }
     */
    public static AsyncSendResponse asyncsendText2User(String userId, String message) {
        return asyncsendV2(ListUtil.of(userId), "text", message);
    }

    /**
     * 发送卡片
     * @param userId 用户id
     * @param title 标题
     * @param markdown 内容
     * @param singleTitle 详情按钮
     * @param singleUrl 详情链接
     * @return {@link AsyncSendResponse }
     */
    public static AsyncSendResponse asyncsendActionCard2User(String userId, String title, String markdown, String singleTitle, String singleUrl) {
        return asyncsendV2(ListUtil.of(userId), "action_card", JSONUtil.toJsonStr(Dict.of("title",title,"markdown",markdown,"singleTitle", singleTitle, "singleUrl", singleUrl)));
    }

}
